package com.sun.huazhi.aitaskservice.common.resilience;

import com.sun.huazhi.aitaskservice.DTO.response.KnowledgeUploadResponse;
import io.github.resilience4j.bulkhead.annotation.Bulkhead;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.github.resilience4j.retry.annotation.Retry;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import java.util.function.Supplier;
@Slf4j
@Component
public class ResilientServiceExecutor {

    @RateLimiter(name = "aiRateLimit", fallbackMethod = "rateLimitFallback")
    @Retry(name = "aiRetry", fallbackMethod = "retryFallback")
    @Bulkhead(name = "aiBulkhead", fallbackMethod = "bulkheadFallback", type = Bulkhead.Type.SEMAPHORE)
    @CircuitBreaker(name = "aiService", fallbackMethod = "circuitBreakerFallback")
    public <T> Mono<ResponseEntity<T>> execute(Supplier<Mono<ResponseEntity<T>>> supplier) {
        log.info("开始执行受保护服务...");
        return supplier.get()
                .doOnSuccess(resp -> log.info("服务调用成功"))
                .doOnError(e -> log.error("服务执行异常: {}", e.getMessage()));
    }

    public <T> Mono<ResponseEntity<T>> rateLimitFallback(Supplier<Mono<ResponseEntity<T>>> supplier, Throwable t) {
        log.warn("RateLimit 限流触发: {}", t.getMessage());
        return fallbackResponse("请求过于频繁，请稍后重试。");
    }

    public <T> Mono<ResponseEntity<T>> retryFallback(Supplier<Mono<ResponseEntity<T>>> supplier, Throwable t) {
        log.warn("Retry 重试失败: {}", t.getMessage());
        return fallbackResponse("服务暂时不可用，请稍后重试。");
    }

    public <T> Mono<ResponseEntity<T>> bulkheadFallback(Supplier<Mono<ResponseEntity<T>>> supplier, Throwable t) {
        log.warn("Bulkhead 并发限制触发: {}", t.getMessage());
        return fallbackResponse("服务压力过大，请稍后重试。");
    }

    public <T> Mono<ResponseEntity<T>> circuitBreakerFallback(Supplier<Mono<ResponseEntity<T>>> supplier, Throwable t) {
        log.warn("CircuitBreaker 熔断触发: {}", t.getMessage());
        return fallbackResponse("服务故障保护，请稍后重试。");
    }

    private <T> Mono<ResponseEntity<T>> fallbackResponse(String message) {
        return Mono.just(ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
                .body((T) new KnowledgeUploadResponse("FAIL"+ message)));
    }
}
